package maze

import (
	"fmt"
	"syscall/js"
	"time"
)

var (
	global   = js.Global()
	document = global.Get("document")
	running  bool
)

// create_maze 生成迷宫
func create_maze(this js.Value, jv []js.Value) interface{} {
	var (
		width  = 30
		height = 30
	)
	if len(jv) >= 2 {
		height = jv[1].Int()
	}
	if len(jv) >= 1 {
		width = jv[0].Int()
	}
	currentMaze = Generate(width, height) // 生成迷宫
	maze_table := document.Call("getElementById", "maze_table")
	maze_table.Set("innerHTML", "")
	for i := range currentMaze {
		tr := document.Call("createElement", "tr") // 创建tr
		for j := range currentMaze[i] {
			td := document.Call("createElement", "td")
			span := document.Call("createElement", "span")
			td.Call("appendChild", span) // 将span加到td
			if currentMaze[i][j] {
				td.Get("style").Set("backgroundColor", "black") // 墙
			}
			tr.Call("appendChild", td) // 追加td到tr
		}
		maze_table.Call("appendChild", tr) // 追加tr到table
	}
	return js.Undefined()
}

func maze_clean_main() {
	maze_table := document.Call("getElementById", "maze_table")
	tr_nodes := maze_table.Get("childNodes")
	for i := 0; i < tr_nodes.Get("length").Int(); i++ {
		td_nodes := tr_nodes.Index(i).Get("childNodes")
		for j := 0; j < td_nodes.Get("length").Int(); j++ {
			span := td_nodes.Index(j).Get("childNodes").Index(0)
			span.Set("innerHTML", "")
		}
	}
}

func maze_clean(this js.Value, jv []js.Value) interface{} {
	maze_clean_main()
	return js.Undefined()
}

func maze_run(mode MazeRunMode) {
	go func() {
		if running {
			global.Call("alert", "already running...")
			return
		}
		running = true
		defer func() {
			running = false
		}()

		fmt.Println("running...")
		maze_clean_main();
		res := currentMaze.Run(mode)
		if len(res) == 0 {
			global.Call("alert", "dead maze!")
			return
		}
		maze_table := document.Call("getElementById", "maze_table")
		for i := len(res) - 1; i >= 0; i-- {
			p := res[i]
			span := maze_table.Get("childNodes").Index(p.Y).Get("childNodes").Index(p.X).Get("childNodes").Index(0);
			span.Set("innerHTML", "*")
			time.Sleep(1e8)
		}
		global.Call("alert", "complete!")
		return
	}()
}

func maze_run_normal(this js.Value, jv []js.Value) interface{} {
	maze_run(MazeRunTypeNormal)
	return js.Undefined()
}

func maze_run_breadth(this js.Value, jv []js.Value) interface{} {
	maze_run(MazeRunTypeBreadth)
	return js.Undefined()
}
